/*
 * Ascent MMORPG Server
 * Copyright (C) 2005-2008 Ascent Team <http://www.ascentemu.com/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef __SPELL_H
#define __SPELL_H

#include "SpellFailure.h"
#include "StdAfx.h"

class WorldSession;
class Unit;
//class DynamicObj; Not used anywhere
class Player;
class Item;
class Group;
class Aura;
/* Spell Ranges:(for 1.10.2)
Range ID|Range|Description
1       0-0     Self Only
2       0-5     Combat Range
3       0-20    Short Range
4       0-30    Medium Range
5       0-40    Long Range
6       0-100   Vision Range
7       0-10    Very Short Range
8       10-20   Short Range
9       10-30   Medium Range
10      10-40   Long Range
11      0-15    Shorter Range
12      0-5     Interact Range
13      0-50000 Anywhere
14      0-60    Extra Long Range
34      0-25    Medium-Short Range
35      0-35    Medium-Long Range
36      0-45    Longer Range
37      0-50    Extended Range
38      10-25   Extra Medium Range
54      5-30    Geoff Monster Shoot
74      8-30    Ranged Weapon
94      8-40    Sting
95      8-25    Charge
96      0-2     Trap
114     8-35    Hunter Range Hunter
134     0-80    Tower 80 Tower
135     0-100   Tower 100 Tower
*/

/*FLAT PCT
0    x    x
1    x    x
2    x    x
3         x
4    x
5    x    x
6    x    x
7    x =  x//both add % to crit
8    x    x
9         x
10   x    x
11   x    x
12   x
13    
14   x    x
15        x
16   x    
17   x
18   x    x
19   x
20        x
21    
22   x    x
23   x(enslave dem)
24    
25
26   x(obsolete)
27        x
*/

//wooohooo, there are 19 spells that actually require to add a proccounter for these 
//first spell catched is "presence of mind"
//an ugly solution would be to add a proc flag to remove aura on event it should expire (like attack or cast) but that is only if count=1
enum SPELL_MODIFIER_TYPE
{
    SMT_DAMAGE_DONE         =0,// increases the damage done by spell by x% dmg (flat as x dmg)
    SMT_DURATION            =1,// spell    duration increase // GOOD
    //hmm shaman spirit weapon clearly states that this should be parry chance
    SMT_THREAT_REDUCED      =2,// reduces threat generated by this spell by x% // GOOD but need more work
    SMT_ATTACK_POWER_AND_DMG_BONUS=3,// attacker power bonus for ability +x% // Seal of crusader also takes this as dmg bonus + power bonus 
    SMT_BLOCK               =4,// block additional attack // GOOD and need work //Not used in 2.1.1 ?
    SMT_RANGE               =5,// spell range bonus // GOOD
    SMT_RADIUS              =6,// spell radius bonus // GOOD
    SMT_CRITICAL            =7,// critical chance bonus // GOOD //only 1 example in 2.1.1
    SMT_SPELL_VALUE         =8,// dummy effect // needs work is not only pets Hp but effect of spells to
    SMT_NONINTERRUPT        =9,// x% chance not to be interrupted by received damage (no flat)
    SMT_CAST_TIME           =10,// cast time decrease // GOOD
    SMT_COOLDOWN_DECREASE   =11,// cooldown decrease <-probably fully handled by client // GOOD
    SMT_EFFECT              = 12,//used by shaman elemental weapons and another spell
//    SMT_SPEED             =12,// movement speed, while given spell is active(flat is %) // TODO CHECK! ok this is not speed and is used with 23 misc to sometimes so is odd
    // 13 dont exist spells with it
    SMT_COST                =14,// mana/energy/rage cost reduction // GOOD
    SMT_CRITICAL_DAMAGE     =15,// increases critical strike damage bonus (no flat)
    SMT_HITCHANCE           =16,// enemy resist chance decrease (flat as %) // GOOD need work
    SMT_ADDITIONAL_TARGET   =17,// Your Healing Wave will now jump to additional nearby targets. Each jump reduces the effectiveness of the heal by 80% // GOOD
    SMT_TRIGGER             =18,// adds/increases chance to trigger some spell for example increase chance to apply poisons or entaglin // GOOD need work
    SMT_TIME                =19,// delay for nova, redirection time bonus for totem,maybe smth else // GOOD need work
    SMT_JUMP_REDUCE         =20,// Increases the amount healed by Chain Heal to targets beyond the first by x%. (no flat)
    //SMT_CAST_TIME2        =21,// this one looks like cast time...
	//!!! most spells have both SMT_DAMAGE_DONE and this value. Be carefull case there is no need to apply both !
    SMT_SPELL_VALUE_PCT		=22,// damage done by ability by x% : SELECT id,name,description FROM dbc_spell where (EffectApplyAuraName_1=108 and EffectMiscValue_1=22) or (EffectApplyAuraName_2=108 and EffectMiscValue_2=22) or (EffectApplyAuraName_3=108 and EffectMiscValue_3=22)  its DoT actually
    SMT_UNKNOWN23           =23,// this seems to be some scripted effect. From 8 spells not even 1 has description what it does
    SMT_PENALTY             =24,// This is a modifer for the amount of +spell damage applied to the spell group from spell bonuses
    // 25 dont exist spells with it
    // 26 is obsolete stuff
    SMT_EFFECT_BONUS        =27,// mana lost cost per point of damage taken for mana shield,Health or Mana gained from Drain Life and Drain Mana increased by x%.
    SMT_RESIST_DISPEL       =28,// TODO NEEDS WORK :D
};


static void SM_FFValue( int32* m, float* v, uint64 group )
{
    if( m == 0 )
		return;

    for( uint32 x = 0; x < SPELL_GROUPS; x++ )
        if( ( (uint64)1 << x) & group )
            (*v) += m[x];
}

static void SM_FIValue( int32* m, int32* v, uint64 group )
{
    if( m == 0 )
		return;

    for( uint32 x = 0; x < SPELL_GROUPS; x++ )
        if( ( (uint64)1 << x ) & group )
		{
            (*v) += m[x];
		}
}

static void SM_PIValue( int32* m, int32* v, uint64 group )
{
    if( m == 0 )
		return;

    for( uint32 x = 0; x < SPELL_GROUPS; x++ )
        if( ( (uint64)1 << x ) & group )
            (*v) += ( (*v) * m[x] ) / 100;
}

static void SM_PFValue( int32* m, float* v, uint64 group )
{
    if( m == 0 )
		return;
    
    for( uint32 x = 0; x < SPELL_GROUPS; x++ )
        if( ( (uint64)1 << x ) & group )
            (*v) += ( (*v) * m[x] ) / 100.0f;
}

//bool IsBeneficSpell(SpellEntry *sp);
//AI_SpellTargetType RecommandAISpellTargetType(SpellEntry *sp);

enum SPELL_DMG_TYPE // SPELL_ENTRY_Spell_Dmg_Type
{
	SPELL_DMG_TYPE_NONE   = 0,
	SPELL_DMG_TYPE_MAGIC  = 1,
	SPELL_DMG_TYPE_MELEE  = 2,
	SPELL_DMG_TYPE_RANGED = 3
};

// value's for SendSpellLog
enum SPELL_LOG
{
    SPELL_LOG_NONE,
    SPELL_LOG_MISS,
    SPELL_LOG_RESIST,
    SPELL_LOG_DODGE,
    SPELL_LOG_PARRY,
    SPELL_LOG_BLOCK,
    SPELL_LOG_EVADE,
    SPELL_LOG_IMMUNE,
    SPELL_LOG_IMMUNE2,
    SPELL_LOG_DEFLECT,
    SPELL_LOG_ABSORB,
    SPELL_LOG_REFLECT
};

enum SpellCastTargetFlags
{
    TARGET_FLAG_SELF                = 0x0000, // they are checked in following order
    TARGET_FLAG_UNK1                = 0x0001,
    TARGET_FLAG_UNIT                = 0x0002,
    TARGET_FLAG_UNK2                = 0x0004,
    TARGET_FLAG_UNK3                = 0x0008,
    TARGET_FLAG_ITEM                = 0x0010,
    TARGET_FLAG_SOURCE_LOCATION     = 0x0020,
    TARGET_FLAG_DEST_LOCATION       = 0x0040,
    TARGET_FLAG_UNK6                = 0x0080,
    TARGET_FLAG_UNK7                = 0x0100,
    TARGET_FLAG_CORPSE              = 0x0200,
    TARGET_FLAG_UNK8                = 0x0400,
    TARGET_FLAG_OBJECT              = 0x0800,
    TARGET_FLAG_TRADE_ITEM          = 0x1000,
    TARGET_FLAG_STRING              = 0x2000,
    TARGET_FLAG_UNK9                = 0x4000,
    TARGET_FLAG_CORPSE2             = 0x8000
};
#ifndef NEW_PROCFLAGS 
enum procFlags
{
    PROC_NULL                       = 0x0,
    PROC_ON_ANY_HOSTILE_ACTION      = 0x1,
    PROC_ON_GAIN_EXPIERIENCE        = 0x2,
    PROC_ON_MELEE_ATTACK            = 0x4,
    PROC_ON_CRIT_HIT_VICTIM         = 0x8,
    PROC_ON_CAST_SPELL              = 0x10,
    PROC_ON_PHYSICAL_ATTACK_VICTIM  = 0x20,
    PROC_ON_RANGED_ATTACK           = 0x40,
    PROC_ON_RANGED_CRIT_ATTACK      = 0x80,
//    PROC_ON_UNK_DAMAGE_VICTIM       = 0x80,//seems to be on ranged dmg victim 99% sure('each melee or ranged attack' -> flag =680 (dec))
    PROC_ON_PHYSICAL_ATTACK         = 0x100,
    PROC_ON_MELEE_ATTACK_VICTIM     = 0x200,
//    PROC_ON_ANY_ACTION              = 0x400,
    PROC_ON_SPELL_LAND              = 0x400,
//    PROC_UNK_DEFILLED               = 0x800,
    PROC_ON_RANGED_CRIT_ATTACK_VICTIM = 0x800,
    PROC_ON_CRIT_ATTACK             = 0x1000,
    PROC_ON_RANGED_ATTACK_VICTIM    = 0x2000,
//    PROC_ANYTIME                    = 0x4000,
    PROC_ON_PRE_DISPELL_AURA_VICTIM = 0x4000,
//    PROC_UNK2_DEFILLED              = 0x8000,
	PROC_ON_SPELL_LAND_VICTIM       = 0x8000,//custom flag. PROC only when spell landed on victim
    PROC_ON_CAST_SPECIFIC_SPELL     = 0x10000,
    PROC_ON_SPELL_HIT_VICTIM        = 0x20000,
    PROC_ON_SPELL_CRIT_HIT_VICTIM   = 0x40000,
//    PROC_ON_UNK2_DAMAGE_VICTIM      = 0x80000,
    PROC_ON_TARGET_DIE		        = 0x80000,
    PROC_ON_ANY_DAMAGE_VICTIM       = 0x100000,
	PROC_ON_TRAP_TRIGGER            = 0x200000, //triggers on trap activation)
    PROC_ON_AUTO_SHOT_HIT           = 0x400000,
    PROC_ON_ABSORB                  = 0x800000,
    PROC_ON_RESIST_VICTIM           = 0x1000000,//added it as custom, maybe already exists in another form ?
    PROC_ON_DODGE_VICTIM            = 0x2000000,//added it as custom, maybe already exists in another form ?
    PROC_ON_DIE                     = 0x4000000,//added it as custom, maybe already exists in another form ?
    PROC_REMOVEONUSE                = 0x8000000,//remove prochcharge only when it is used
    PROC_MISC                       = 0x10000000,//our custom flag to decide if proc dmg or shield
    PROC_ON_BLOCK_VICTIM            = 0x20000000,//added it as custom, maybe already exists in another form ?
    PROC_ON_SPELL_CRIT_HIT          = 0x40000000,//added it as custom, maybe already exists in another form ?
    PROC_TARGET_SELF               = 0x80000000,//our custom flag to decide if proc target is self or victim
};
#else
//REMEMBER: Wands r not ranged based weapons. So it shouldn't be any ranged proc when u hit with wands!
enum procFlags
{
	PROC_NULL                          = 0x0,
	PROC_ON_NPC_ACTION                 = 0x1, //on GO action too btw. related to quests in general.
	PROC_ON_XP_GAIN                    = 0x2, //on honor gain too btw.
	PROC_ON_MELEE_HIT                  = 0x4, //on successful white melee attack
	PROC_ON_MELEE_HIT_VICTIM           = 0x8, //on successful white melee attack victim
	PROC_ON_MELEE_ABILITY_LAND         = 0x10, //on successful melee ability attack. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_MELEE_ABILITY_LAND_VICTIM  = 0x20, //on successful melee ability victim but not white damage. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_RANGED_HIT                 = 0x40,  //on successful ranged white attack
	PROC_ON_RANGED_HIT_VICTIM          = 0x80,  //on successful ranged white attack victim
	PROC_ON_RANGED_ABILITY_LAND        = 0x100, //on successful ranged ability attack. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_RANGED_ABILITY_LAND_VICTIM = 0x200,  //on successful ranged ability victim but not white damage. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_CAST_SPELL                 = 0x400, //on nonability (spell) cast. Spells that was resisted don't proc with this flag
	PROC_ON_CAST_SPELL_VICTIM          = 0x800,  //on nonability (spell) cast victim. Spells that was resisted don't proc with this flag.
	PROC_ON_ANY_DAMAGE                 = 0x1000, // mb wrong
	PROC_ON_ANY_DAMAGE_VICTIM          = 0x2000, // mb wrong
	PROC_ON_HEALSPELL_LAND             = 0x4000, //on heal (direct or HoT) spell land.
	PROC_ON_HEALSPELL_LAND_VICTIM      = 0x8000,  //on heal (direct or HoT) spell land victim.
	PROC_ON_HARMFULSPELL_LAND          = 0x10000, //on harmfull spell land (DoT damage not included in this flag!)
	PROC_ON_HARMFULSPELL_LAND_VICTIM   = 0x20000, //on harmfull spell land victim (DoT damage not included in this flag!)
	PROC_ON_DOT_DAMAGE                 = 0x40000, //on harmfull non direct damage (DoTs)
	PROC_ON_DOT_DAMAGE_VICTIM          = 0x80000,  //on harmfull non direct damage (DoTs) victim
	PROC_REMOVEONUSE                   = 0x100000, //something supercustom. 99% wrong :P used by bombs and grenades in general.
	PROC_ON_TRAP_TRIGGER               = 0x200000,
	PROC_UNUSED1                       = 0x400000,
	PROC_ON_OFFHAND_HIT                = 0x800000, //only 1 spellname "Combat Potency"
	PROC_ON_UNK1                       = 0x1000000,//only 1 spellname "Captured Totem"
};
enum customProcFlags
{
	CUSTOMPROC_NULL                       = 0x0;
	CUSTOMPROC_ON_CRIT                    = 0x1; //doesn't matter victim or not. 
	CUSTOMPROC_ON_MISS_VICTIM             = 0x2;
	CUSTOMPROC_ON_DODGE_VICTIM            = 0x4;
	CUSTOMPROC_ON_BLOCK_VICTIM            = 0x8;
	CUSTOMPROC_ON_PARRY_VICTIM            = 0x10;
	CUSTOMPROC_ON_RESIST_VICTIM           = 0x20;
	CUSTOMPROC_ON_DIE                     = 0x40;//proc on our death
	CUSTOMPROC_ON_FINISHMOVE              = 0x80; //procs when we use finish move ability
	CUSTOMPROC_ON_ADDCOMBO                = 0x100; //procs when we use ability with +combo point
	CUSTOMPROC_PROC_ON_SELF               = 0x200; //proc on self
};
#endif

enum CastInterruptFlags
{
    CAST_INTERRUPT_NULL            = 0x0,
    CAST_INTERRUPT_ON_SILENCE      = 0x1,
    CAST_INTERRUPT_ON_SLEEP        = 0x2, // could be wrong
    CAST_INTERRUPT_ON_STUNNED      = 0x4, // could be wrong
    CAST_INTERRUPT_ON_MOVEMENT     = 0x8,
    CAST_INTERRUPT_ON_DAMAGE_TAKEN = 0x10
};

enum AuraInterruptFlags
{
    AURA_INTERRUPT_NULL                       = 0x0,
    AURA_INTERRUPT_ON_HOSTILE_SPELL_INFLICTED = 0x1,
    AURA_INTERRUPT_ON_ANY_DAMAGE_TAKEN        = 0x2,
    AURA_INTERRUPT_ON_UNK1                    = 0x4,
    AURA_INTERRUPT_ON_MOVEMENT                = 0x8, // could be AURA_INTERRUPT_ON_MOVEMENT
    AURA_INTERRUPT_ON_UNK2                    = 0x10,
    AURA_INTERRUPT_ON_UNK3                    = 0x20,
    AURA_INTERRUPT_ON_UNUSED1                 = 0x40,
    AURA_INTERRUPT_ON_SLOWED                  = 0x80,
    AURA_INTERRUPT_ON_LEAVE_WATER             = 0x100, // could be AURA_INTERRUPT_ON_LEAVE_CURRENT_SURFACE
    AURA_INTERRUPT_ON_UNUSED2                 = 0x200,
    AURA_INTERRUPT_ON_UNK4                    = 0x400,
    AURA_INTERRUPT_ON_UNK5                    = 0x800,
    AURA_INTERRUPT_ON_START_ATTACK            = 0x1000,
    AURA_INTERRUPT_ON_UNK6                    = 0x2000,
    AURA_INTERRUPT_ON_UNUSED3                 = 0x4000,
    AURA_INTERRUPT_ON_CAST_SPELL              = 0x8000,
    AURA_INTERRUPT_ON_UNK7                    = 0x10000,
    AURA_INTERRUPT_ON_MOUNT                   = 0x20000,
    AURA_INTERRUPT_ON_STAND_UP                = 0x40000,
    AURA_INTERRUPT_ON_LEAVE_AREA              = 0x80000,
    AURA_INTERRUPT_ON_INVINCIBLE              = 0x100000,
    AURA_INTERRUPT_ON_STEALTH                 = 0x200000,
    AURA_INTERRUPT_ON_UNK8                    = 0x400000,
};

enum ChannelInterruptFlags
{
    CHANNEL_INTERRUPT_NULL  = 0x0,
    CHANNEL_INTERRUPT_ON_1  = 0x1,
    CHANNEL_INTERRUPT_ON_2  = 0x2,
    CHANNEL_INTERRUPT_ON_3  = 0x4,
    CHANNEL_INTERRUPT_ON_4  = 0x8,
    CHANNEL_INTERRUPT_ON_5  = 0x10,
    CHANNEL_INTERRUPT_ON_6  = 0x20,
    CHANNEL_INTERRUPT_ON_7  = 0x40,
    CHANNEL_INTERRUPT_ON_8  = 0x80,
    CHANNEL_INTERRUPT_ON_9  = 0x100,
    CHANNEL_INTERRUPT_ON_10 = 0x200,
    CHANNEL_INTERRUPT_ON_11 = 0x400,
    CHANNEL_INTERRUPT_ON_12 = 0x800,
    CHANNEL_INTERRUPT_ON_13 = 0x1000,
    CHANNEL_INTERRUPT_ON_14 = 0x2000,
    CHANNEL_INTERRUPT_ON_15 = 0x4000,
    CHANNEL_INTERRUPT_ON_16 = 0x8000,
    CHANNEL_INTERRUPT_ON_17 = 0x10000,
    CHANNEL_INTERRUPT_ON_18 = 0x20000
};

enum Attributes
{
	ATTRIBUTES_NULL								= 0x0,
	ATTRIBUTES_UNK2								= 0x1,
	ATTRIBUTES_UNK3								= 0x2, // related to ranged??
	ATTRIBUTE_ON_NEXT_ATTACK					= 0x4,
	ATTRIBUTES_UNUSED0							= 0x8,
	ATTRIBUTES_UNK6								= 0x10,
	ATTRIBUTES_UNK7								= 0x20, // Tradeskill recipies
	ATTRIBUTES_PASSIVE							= 0x40,
	ATTRIBUTES_NO_VISUAL_AURA					= 0x80,
	ATTRIBUTES_UNK10							= 0x100,	//seems to be afflicts pet
	ATTRIBUTES_UNK11							= 0x200, // looks like temp enchants.
	ATTRIBUTES_UNK12							= 0x400, //completely the same as ATTRIBUTE_ON_NEXT_ATTACK for class spells. So difference somewhere in mob abilities.
	ATTRIBUTES_UNK13							= 0x800,
	ATTRIBUTES_UNUSED1							= 0x1000,
	ATTRIBUTES_UNUSED2							= 0x2000,
	ATTRIBUTES_UNUSED3							= 0x4000,
	ATTRIBUTES_ONLY_OUTDOORS					= 0x8000,
	ATTRIBUTES_UNK								= 0x10000,
	ATTRIBUTES_REQ_STEALTH						= 0x20000,
	ATTRIBUTES_UNK20							= 0x40000,//it's not : must be behind
	ATTRIBUTES_UNK21							= 0x80000,
	ATTRIBUTES_STOP_ATTACK						= 0x100000,//switch off auto attack on use. Maim,Gouge,Disengage,Polymorph etc
	ATTRIBUTES_CANT_BE_DPB				    	= 0x200000,//can't be dodged, blocked, parried
	ATTRIBUTES_UNK24							= 0x400000, // related to ranged
	ATTRIBUTES_UNK25							= 0x800000,
	ATTRIBUTES_MOUNT_CASTABLE					= 0x1000000, //castable on mounts
	ATTRIBUTES_TRIGGER_COOLDOWN			        = 0x2000000, //also requires atributes ex = 32 ?
	ATTRIBUTES_UNK28							= 0x4000000,
	ATTRIBUTES_UNK29							= 0x8000000,
	ATTRIBUTES_REQ_OOC							= 0x10000000, //     ATTRIBUTES_REQ_OUT_OF_COMBAT
    ATTRIBUTES_IGNORE_INVULNERABILITY           = 0x20000000, //debuffs that can't be removed by any spell and spells that can't be resisted in any case
	ATTRIBUTES_UNK32							= 0x40000000, // seems like IS_DIMINISHING but some spells not there (f.e. Gouge)
};

enum AttributesEx
{
	ATTRIBUTESEX_NULL                         = 0x0,
	ATTRIBUTESEX_UNK2                         = 0x1, // pet summonings
	ATTRIBUTESEX_DRAIN_WHOLE_MANA             = 0x2,
	ATTRIBUTESEX_UNK4                         = 0x4,
	ATTRIBUTESEX_UNK5                         = 0x8,
	ATTRIBUTESEX_UNK6                         = 0x10, // stealth effects but Rockbiter wtf 0_0
	ATTRIBUTESEX_NOT_BREAK_STEALTH            = 0x20,
	ATTRIBUTESEX_UNK8                         = 0x40,
	ATTRIBUTESEX_UNK9                         = 0x80,
	ATTRIBUTESEX_UNK10                        = 0x100,
	ATTRIBUTESEX_UNK11                        = 0x200,
	ATTRIBUTESEX_UNK12                        = 0x400,
	ATTRIBUTESEX_UNK13                        = 0x800,
	ATTRIBUTESEX_UNK14                        = 0x1000, // related to pickpocket
	ATTRIBUTESEX_UNK15                        = 0x2000, // related to remote control
	ATTRIBUTESEX_UNK16                        = 0x4000,
	ATTRIBUTESEX_UNK17                        = 0x8000, // something like "grant immunity"
	ATTRIBUTESEX_UNK18                        = 0x10000, // something like "grant immunity" too
	ATTRIBUTESEX_REMAIN_OOC                   = 0x20000,
	ATTRIBUTESEX_UNK20                        = 0x40000,
	ATTRIBUTESEX_UNK21                        = 0x80000,
	ATTRIBUTESEX_UNK22                        = 0x100000, // related to "Finishing move" and "Instantly overpowers"
	ATTRIBUTESEX_UNK23                        = 0x200000,
	ATTRIBUTESEX_UNK24                        = 0x400000, // only related to "Finishing move"
	ATTRIBUTESEX_UNK25                        = 0x800000, // related to spells like "ClearAllBuffs"
	ATTRIBUTESEX_UNK26                        = 0x1000000, // FISHING SPELLS
	ATTRIBUTESEX_UNK27                        = 0x2000000, // related to "Detect" spell
	ATTRIBUTESEX_UNK28                        = 0x4000000,
	ATTRIBUTESEX_UNK29                        = 0x8000000,
	ATTRIBUTESEX_UNK30                        = 0x10000000,
	ATTRIBUTESEX_UNK31                        = 0x20000000,
	ATTRIBUTESEX_UNK32                        = 0x40000000, // Overpower
};

enum Flags3
{
	FLAGS3_NULL               = 0x0,
	FLAGS3_UNK2               = 0x1,
	FLAGS3_UNK3               = 0x2,    // Can be used while stealthed
	FLAGS3_UNK4               = 0x4,    // request pet maybe
	FLAGS3_UNK5               = 0x8,    // something todo with temp enchanted items
	FLAGS3_PARTY_EFFECTING_AURA = 0x10, // Party affecting aura's
	FLAGS3_ACTIVATE_AUTO_SHOT = 0x20,   // spell that enable's auto shoot
	FLAGS3_UNK8               = 0x40,   //Polymorph spells
	FLAGS3_UNK9               = 0x80,
	FLAGS3_UNUSED1            = 0x100,
	FLAGS3_UNK11              = 0x200,  // used by 2 spells, 30421 | Nether Portal - Perseverence and  30466 | Nether Portal - Perseverence
	FLAGS3_TAME_X             = 0x400,  // tame [creature]
	FLAGS3_FUNNEL             = 0x800,  // only funnel spells
	FLAGS3_UNK14              = 0x1000, // swipe / Cleave spells
	FLAGS3_ENCHANT_OWN_ONLY   = 0x2000, // no trade window targets, BoE items get soulbound to you
	FLAGS3_SPELL_PLAYER_EVENT = 0x4000, // Player event's like logging in, finishing quests, triggering cinematic, being adored, Heartbroken etc
	FLAGS3_UNUSED3            = 0x8000,
	FLAGS3_CONTROL_UNIT       = 0x10000, // PvP Controller, RC, Creature taming, Taming Lesson
	FLAGS3_REQ_RANGED_WEAPON  = 0x20000, // this is shit and has nothing to do with auto shot
	FLAGS3_REVIVE_PET         = 0x40000, // actually 1 spell, revive pet
	FLAGS3_UNK21              = 0x80000, // this is a group of spells that are triggered by something. (I have no clue on how to name this one)
	FLAGS3_REQ_BEHIND_TARGET  = 0x100000, //wrong
	FLAGS3_UNK23              = 0x200000,
	FLAGS3_UNK24              = 0x400000,
	FLAGS3_UNK25              = 0x800000,
	FLAGS3_UNK26              = 0x1000000,
	FLAGS3_UNK27              = 0x2000000,
	FLAGS3_UNK28              = 0x4000000,
	FLAGS3_UNK29              = 0x8000000, // fishing spells and enchanting weapons
	FLAGS3_UNK30              = 0x10000000, // some secondairy spell triggers, especialy for lightning shield alike spells
	FLAGS3_UNK31              = 0x20000000,
	FLAGS3_UNK32              = 0x40000000,
};

enum Flags4
{
	FLAGS4_BG_ONLY                      = 0x800,
	FLAGS4_PLAYER_RANGED_SPELLS         = 0x8000,
	CAN_PERSIST_AND_CASTED_WHILE_DEAD   = 0x100000,
	FLAGS4_PLAYER_RANGED_WAND           = 0x400000
};

enum Flags5
{
	FLAGS5_PROCCHANCE_COMBOBASED        = 0x2,
	FLAGS5_ONLY_IN_OUTLANDS             = 0x4000000,
};

enum SpellCastFlags
{
    CAST_FLAG_UNKNOWN1           = 0x2,
    CAST_FLAG_UNKNOWN2           = 0x10, // no idea yet, i saw it in blizzard spell
    CAST_FLAG_AMMO               = 0x20 // load ammo display id (uint32) and ammo inventory type (uint32)
};

enum School
{
    SCHOOL_NORMAL = 0,
    SCHOOL_HOLY   = 1,
    SCHOOL_FIRE   = 2,
    SCHOOL_NATURE = 3,
    SCHOOL_FROST  = 4,
    SCHOOL_SHADOW = 5,
    SCHOOL_ARCANE = 6
};

// converting schools for 2.4.0 client
static const uint32 g_spellSchoolConversionTable[SCHOOL_ARCANE+1] = {
	1,				// SCHOOL_NORMAL
	2,				// SCHOOL_HOLY
	4,				// SCHOOL_FIRE
	8,				// SCHOOL_NATURE
	16,				// SCHOOL_FROST
	32,				// SCHOOL_SHADOW
	64,				// SCHOOL_ARCANE
};

enum ReplenishType
{
    REPLENISH_UNDEFINED = 0,
    REPLENISH_HEALTH    = 20,
    REPLENISH_MANA      = 21,
    REPLENISH_RAGE      = 22 //don't know if rage is 22 or what, but will do for now
};

enum SpellTargetType
{
    TARGET_TYPE_NULL       = 0x0,
    TARGET_TYPE_BEAST      = 0x1,
    TARGET_TYPE_DRAGONKIN  = 0x2,
    TARGET_TYPE_DEMON      = 0x4,
    TARGET_TYPE_ELEMENTAL  = 0x8,
    TARGET_TYPE_GIANT      = 0x10,
    TARGET_TYPE_UNDEAD     = 0x20,
    TARGET_TYPE_HUMANOID   = 0x40,
    TARGET_TYPE_CRITTER    = 0x80,
    TARGET_TYPE_MECHANICAL = 0x100,
};

/****************SpellExtraFlags*****************/
/* SpellExtraFlags defines                      */
/*                                              */
/* Used for infront check and other checks      */
/* when they are not in spell.dbc               */
/*                                              */
/************************************************/
#define SPELL_EXTRA_INFRONT 1
#define SPELL_EXTRA_BEHIND  2
#define SPELL_EXTRA_UNDEF0  4 // not used yet
#define SPELL_EXTRA_UNDEF1  8 // not used yet


/***************Ranged spellid*******************/
/* Note: These spell id's are checked for 2.0.x */
/************************************************/
#define SPELL_RANGED_GENERAL    3018
#define SPELL_RANGED_THROW      2764
#define SPELL_RANGED_WAND       5019

#pragma pack(push,1)
struct TeleportCoords
{
    uint32 id;
    uint32 mapId;
    float x;
    float y;
    float z;
};
#pragma pack(pop)

struct TotemSpells
{
    uint32 spellId;
    uint32 spellToCast[3];
};

enum LOCKTYPES{
    LOCKTYPE_PICKLOCK               =1,
    LOCKTYPE_HERBALISM              =2,
    LOCKTYPE_MINING                 =3,
    LOCKTYPE_DISARM_TRAP            =4,
    LOCKTYPE_OPEN                   =5,
    LOCKTYPE_TREASURE               =6,
    LOCKTYPE_CALCIFIED_ELVEN_GEMS   =7,
    LOCKTYPE_CLOSE                  =8,
    LOCKTYPE_ARM_TRAP               =9,
    LOCKTYPE_QUICK_OPEN             =10,
    LOCKTYPE_QUICK_CLOSE            =11,
    LOCKTYPE_OPEN_TINKERING         =12,
    LOCKTYPE_OPEN_KNEELING          =13,
    LOCKTYPE_OPEN_ATTACKING         =14,
    LOCKTYPE_GAHZRIDIAN             =15,
    LOCKTYPE_BLASTING               =16,
    LOCKTYPE_SLOW_OPEN              =17,
    LOCKTYPE_SLOW_CLOSE             =18
};

enum SpellEffects
{
    SPELL_EFFECT_NULL = 0,
    SPELL_EFFECT_INSTANT_KILL,              //    1
    SPELL_EFFECT_SCHOOL_DAMAGE,             //    2    
    SPELL_EFFECT_DUMMY,                     //    3    
    SPELL_EFFECT_PORTAL_TELEPORT,           //    4    
    SPELL_EFFECT_TELEPORT_UNITS,            //    5    
    SPELL_EFFECT_APPLY_AURA,                //    6    
    SPELL_EFFECT_ENVIRONMENTAL_DAMAGE,      //    7    
    SPELL_EFFECT_POWER_DRAIN,               //    8    
    SPELL_EFFECT_HEALTH_LEECH,              //    9    
    SPELL_EFFECT_HEAL,                      //    10    
    SPELL_EFFECT_BIND,                      //    11    
    SPELL_EFFECT_PORTAL,                    //    12
    SPELL_EFFECT_RITUAL_BASE,               //    13
    SPELL_EFFECT_RITUAL_SPECIALIZE,         //    14
    SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL,    //    15
    SPELL_EFFECT_QUEST_COMPLETE,            //    16    
    SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL,    //    17    
    SPELL_EFFECT_RESURRECT,                 //    18    
    SPELL_EFFECT_ADD_EXTRA_ATTACKS,         //    19    
    SPELL_EFFECT_DODGE,                     //    20    
    SPELL_EFFECT_EVADE,                     //    21    
    SPELL_EFFECT_PARRY,                     //    22    
    SPELL_EFFECT_BLOCK,                     //    23    
    SPELL_EFFECT_CREATE_ITEM,               //    24    
    SPELL_EFFECT_WEAPON,                    //    25
    SPELL_EFFECT_DEFENSE,                   //    26
    SPELL_EFFECT_PERSISTENT_AREA_AURA,      //    27    
    SPELL_EFFECT_SUMMON,                    //    28    
    SPELL_EFFECT_LEAP,                      //    29    
    SPELL_EFFECT_ENERGIZE,                  //    30    
    SPELL_EFFECT_WEAPON_PERCENT_DAMAGE,     //    31    
    SPELL_EFFECT_TRIGGER_MISSILE,           //    32    
    SPELL_EFFECT_OPEN_LOCK,                 //    33    
    SPELL_EFFECT_TRANSFORM_ITEM,            //    34    
    SPELL_EFFECT_APPLY_AREA_AURA,           //    35    
    SPELL_EFFECT_LEARN_SPELL,               //    36    
    SPELL_EFFECT_SPELL_DEFENSE,             //    37    
    SPELL_EFFECT_DISPEL,                    //    38    
    SPELL_EFFECT_LANGUAGE,                  //    39
    SPELL_EFFECT_DUAL_WIELD,                //    40    
    SPELL_EFFECT_SUMMON_WILD,               //    41    
    SPELL_EFFECT_SUMMON_GUARDIAN,           //    42    
    SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER,//    43
    SPELL_EFFECT_SKILL_STEP,                //    44    
    SPELL_EFFECT_UNDEFINED_45,              //    45    
    SPELL_EFFECT_SPAWN,                     //    46
    SPELL_EFFECT_TRADE_SKILL,               //    47
    SPELL_EFFECT_STEALTH,                   //    48
    SPELL_EFFECT_DETECT,                    //    49
    SPELL_EFFECT_SUMMON_OBJECT,             //    50    
    //SPELL_EFFECT_TRANS_DOOR,              //    50    
    SPELL_EFFECT_FORCE_CRITICAL_HIT,        //    51
    SPELL_EFFECT_GUARANTEE_HIT,             //    52
    SPELL_EFFECT_ENCHANT_ITEM,              //    53    
    SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY,    //    54    
    SPELL_EFFECT_TAMECREATURE,              //    55    
    SPELL_EFFECT_SUMMON_PET,                //    56    
    SPELL_EFFECT_LEARN_PET_SPELL,           //    57    
    SPELL_EFFECT_WEAPON_DAMAGE,             //    58    
    SPELL_EFFECT_OPEN_LOCK_ITEM,            //    59    
    SPELL_EFFECT_PROFICIENCY,               //    60
    SPELL_EFFECT_SEND_EVENT,                //    61    
    SPELL_EFFECT_POWER_BURN,                //    62
    SPELL_EFFECT_THREAT,                    //    63
    SPELL_EFFECT_TRIGGER_SPELL,             //    64    
    SPELL_EFFECT_HEALTH_FUNNEL,             //    65
    SPELL_EFFECT_POWER_FUNNEL,              //    66
    SPELL_EFFECT_HEAL_MAX_HEALTH,           //    67    
    SPELL_EFFECT_INTERRUPT_CAST,            //    68
    SPELL_EFFECT_DISTRACT,                  //    69
    SPELL_EFFECT_PULL,                      //    70
    SPELL_EFFECT_PICKPOCKET,                //    71
    SPELL_EFFECT_ADD_FARSIGHT,              //    72
    SPELL_EFFECT_SUMMON_POSSESSED,          //    73    
    SPELL_EFFECT_SUMMON_TOTEM,              //    74    
    SPELL_EFFECT_HEAL_MECHANICAL,           //    75
    SPELL_EFFECT_SUMMON_OBJECT_WILD,        //    76
    SPELL_EFFECT_SCRIPT_EFFECT,             //    77    
    SPELL_EFFECT_ATTACK,                    //    78
    SPELL_EFFECT_SANCTUARY,                 //    79
    SPELL_EFFECT_ADD_COMBO_POINTS,          //    80    
    SPELL_EFFECT_CREATE_HOUSE,              //    81
    SPELL_EFFECT_BIND_SIGHT,                //    82
    SPELL_EFFECT_DUEL,                      //    83
    SPELL_EFFECT_STUCK,                     //    84
    SPELL_EFFECT_SUMMON_PLAYER,             //    85
    SPELL_EFFECT_ACTIVATE_OBJECT,           //    86
    SPELL_EFFECT_SUMMON_TOTEM_SLOT1,        //    87    
    SPELL_EFFECT_SUMMON_TOTEM_SLOT2,        //    88    
    SPELL_EFFECT_SUMMON_TOTEM_SLOT3,        //    89    
    SPELL_EFFECT_SUMMON_TOTEM_SLOT4,        //    90    
    SPELL_EFFECT_THREAT_ALL,                //    91
    SPELL_EFFECT_ENCHANT_HELD_ITEM,         //    92
    SPELL_EFFECT_SUMMON_PHANTASM,           //    93
    SPELL_EFFECT_SELF_RESURRECT,            //    94    
    SPELL_EFFECT_SKINNING,                  //    95    
    SPELL_EFFECT_CHARGE,                    //    96    
    SPELL_EFFECT_SUMMON_CRITTER,            //    97    
    SPELL_EFFECT_KNOCK_BACK,                //    98    
    SPELL_EFFECT_DISENCHANT,                //    99    
    SPELL_EFFECT_INEBRIATE,                 //    100    
    SPELL_EFFECT_FEED_PET,                  //    101
    SPELL_EFFECT_DISMISS_PET,               //    102
    SPELL_EFFECT_REPUTATION,                //    103
    SPELL_EFFECT_SUMMON_OBJECT_SLOT1,       //    104
    SPELL_EFFECT_SUMMON_OBJECT_SLOT2,       //    105
    SPELL_EFFECT_SUMMON_OBJECT_SLOT3,       //    106
    SPELL_EFFECT_SUMMON_OBJECT_SLOT4,       //    107
    SPELL_EFFECT_DISPEL_MECHANIC,           //    108    
    SPELL_EFFECT_SUMMON_DEAD_PET,           //    109
    SPELL_EFFECT_DESTROY_ALL_TOTEMS,        //    110
    SPELL_EFFECT_DURABILITY_DAMAGE,         //    111
    SPELL_EFFECT_SUMMON_DEMON,              //    112    
    SPELL_EFFECT_RESURRECT_FLAT,            //    113    
    SPELL_EFFECT_ATTACK_ME,                 //    114
    SPELL_EFFECT_DURABILITY_DAMAGE_PCT,     //    115
    SPELL_EFFECT_SKIN_PLAYER_CORPSE,        //    116
    SPELL_EFFECT_SPIRIT_HEAL,               //    117
    SPELL_EFFECT_SKILL,                     //    118
    SPELL_EFFECT_APPLY_PET_AURA,            //    119    
    SPELL_EFFECT_TELEPORT_GRAVEYARD,        //    120
    SPELL_EFFECT_DUMMYMELEE,                //    121
    SPELL_EFFECT_UNKNOWN1,                  //    122
    SPELL_EFFECT_UNKNOWN2,                  //    123
    SPELL_EFFECT_PLAYER_PULL,               //    124
    SPELL_EFFECT_UNKNOWN4,                  //    125
    SPELL_EFFECT_UNKNOWN5,                  //    126
    SPELL_EFFECT_PROSPECTING,               //    127
    SPELL_EFFECT_UNKNOWN7,                  //    128
    SPELL_EFFECT_UNKNOWN8,                  //    129
    SPELL_EFFECT_UNKNOWN9,                  //    129
    SPELL_EFFECT_UNKNOWN10,                 //    130
    SPELL_EFFECT_UNKNOWN11,                 //    131
    SPELL_EFFECT_UNKNOWN12,                 //    132
    SPELL_EFFECT_FORGET_SPECIALIZATION,     //    133
    SPELL_EFFECT_UNKNOWN14,                 //    134
    SPELL_EFFECT_UNKNOWN15,                 //    135
    SPELL_EFFECT_UNKNOWN16,                 //    136
    SPELL_EFFECT_UNKNOWN17,                 //    137
    SPELL_EFFECT_UNKNOWN18,                 //    138
    SPELL_EFFECT_UNKNOWN19,                 //    139
    SPELL_EFFECT_UNKNOWN20,                 //    140
    SPELL_EFFECT_UNKNOWN21,                 //    141
    SPELL_EFFECT_UNKNOWN22,                 //    142
    SPELL_EFFECT_UNKNOWN23,                 //    143
    TOTAL_SPELL_EFFECTS,                    //    144
};

// spell target system
#define TOTAL_SPELL_TARGET 81 // note: all spells with target type's > 80 are test spells

enum SPELL_ENTRY
{
    SPELL_ENTRY_Id,							//	0
    SPELL_ENTRY_School,						// 	1
    SPELL_ENTRY_Category,					//	2
    SPELL_ENTRY_field4,						//	3
    SPELL_ENTRY_DispelType,					//	4
    SPELL_ENTRY_MechanicsType,				//	5
    SPELL_ENTRY_Attributes,					//	6
    SPELL_ENTRY_AttributesEx,				//	7
    SPELL_ENTRY_Flags3,						//	8
    SPELL_ENTRY_Flags4,						//	9
    SPELL_ENTRY_Flags5,						//	10
    SPELL_ENTRY_unk201_1,					//	11
    SPELL_ENTRY_RequiredShapeShift,			//	12
    SPELL_ENTRY_UNK14,						//	13
    SPELL_ENTRY_Targets,					//	14
    SPELL_ENTRY_TargetCreatureType,			//	15
    SPELL_ENTRY_RequiresSpellFocus,			//	16
    SPELL_ENTRY_CasterAuraState,			//	17
    SPELL_ENTRY_TargetAuraState,			//	18
    SPELL_ENTRY_unk201_2,					//	19
    SPELL_ENTRY_unk201_3,					//	20
    SPELL_ENTRY_CastingTimeIndex,			//	21
    SPELL_ENTRY_RecoveryTime,				//	22
    SPELL_ENTRY_CategoryRecoveryTime,		//	23
    SPELL_ENTRY_InterruptFlags,				//	24
    SPELL_ENTRY_AuraInterruptFlags,			//	25
    SPELL_ENTRY_ChannelInterruptFlags,		//	26
    SPELL_ENTRY_procFlags,					//	27
    SPELL_ENTRY_procChance,					//	28
    SPELL_ENTRY_procCharges,				//	29
    SPELL_ENTRY_maxLevel,					//	30
    SPELL_ENTRY_baseLevel,					//	31
    SPELL_ENTRY_spellLevel,					//	32
    SPELL_ENTRY_DurationIndex,				//	33
    SPELL_ENTRY_powerType,					//	34
    SPELL_ENTRY_manaCost,					//	35
    SPELL_ENTRY_manaCostPerlevel,			//	36
    SPELL_ENTRY_manaPerSecond,				//	37
    SPELL_ENTRY_manaPerSecondPerLevel,		//	38
    SPELL_ENTRY_rangeIndex,					//	39
    SPELL_ENTRY_speed,						//	40
    SPELL_ENTRY_modalNextSpell,				//	41
    SPELL_ENTRY_maxstack,					//	42
    SPELL_ENTRY_Totem_1,					//	43
    SPELL_ENTRY_Totem_2,					//	44
    SPELL_ENTRY_Reagent_1,					//	45
    SPELL_ENTRY_Reagent_2,					//	46
    SPELL_ENTRY_Reagent_3,					//	47
    SPELL_ENTRY_Reagent_4,					//	48
    SPELL_ENTRY_Reagent_5,					//	49
    SPELL_ENTRY_Reagent_6,					//	50
    SPELL_ENTRY_Reagent_7,					//	51
    SPELL_ENTRY_Reagent_8,					//	52
    SPELL_ENTRY_ReagentCount_1,				//	53
    SPELL_ENTRY_ReagentCount_2,				//	54
    SPELL_ENTRY_ReagentCount_3,				//	55
    SPELL_ENTRY_ReagentCount_4,				//	56
    SPELL_ENTRY_ReagentCount_5,				//	57
    SPELL_ENTRY_ReagentCount_6,				//	58
    SPELL_ENTRY_ReagentCount_7,				//	59
    SPELL_ENTRY_ReagentCount_8,				//	60
    SPELL_ENTRY_EquippedItemClass,			//	61
    SPELL_ENTRY_EquippedItemSubClass,		//	62
    SPELL_ENTRY_RequiredItemFlags,			//	63
    SPELL_ENTRY_Effect_1,					//	64
    SPELL_ENTRY_Effect_2,					//	65
    SPELL_ENTRY_Effect_3,					//	66
    SPELL_ENTRY_EffectDieSides_1,			//	67
    SPELL_ENTRY_EffectDieSides_2,			//	68
    SPELL_ENTRY_EffectDieSides_3,			//	69
    SPELL_ENTRY_EffectBaseDice_1,			//	70
    SPELL_ENTRY_EffectBaseDice_2,			//	71
    SPELL_ENTRY_EffectBaseDice_3,			//	72
    SPELL_ENTRY_EffectDicePerLevel_1,		//	73
    SPELL_ENTRY_EffectDicePerLevel_2,		//	74
    SPELL_ENTRY_EffectDicePerLevel_3,		//	75
    SPELL_ENTRY_EffectRealPointsPerLevel_1,	//	76
    SPELL_ENTRY_EffectRealPointsPerLevel_2,	//	77
    SPELL_ENTRY_EffectRealPointsPerLevel_3,	//	78
    SPELL_ENTRY_EffectBasePoints_1,			//	79
    SPELL_ENTRY_EffectBasePoints_2,			//	80
    SPELL_ENTRY_EffectBasePoints_3,			//	81
    SPELL_ENTRY_EffectMechanic_1,			//	82
    SPELL_ENTRY_EffectMechanic_2,			//	83
    SPELL_ENTRY_EffectMechanic_3,			//	84
    SPELL_ENTRY_EffectImplicitTargetA_1,	//	85
    SPELL_ENTRY_EffectImplicitTargetA_2,	//	86
    SPELL_ENTRY_EffectImplicitTargetA_3,	//	87
    SPELL_ENTRY_EffectImplicitTargetB_1,	//	88
    SPELL_ENTRY_EffectImplicitTargetB_2,	//	89
    SPELL_ENTRY_EffectImplicitTargetB_3,	//	90
    SPELL_ENTRY_EffectRadiusIndex_1,		//	91
    SPELL_ENTRY_EffectRadiusIndex_2, 		//	92
    SPELL_ENTRY_EffectRadiusIndex_3, 		//	93
    SPELL_ENTRY_EffectApplyAuraName_1,		//	94
    SPELL_ENTRY_EffectApplyAuraName_2,		//	95
    SPELL_ENTRY_EffectApplyAuraName_3,		//	96
    SPELL_ENTRY_EffectAmplitude_1,			//	97
    SPELL_ENTRY_EffectAmplitude_2,			//	98
    SPELL_ENTRY_EffectAmplitude_3,			//	99
    SPELL_ENTRY_Effectunknown_1,			//	100
    SPELL_ENTRY_Effectunknown_2,			//	101
    SPELL_ENTRY_Effectunknown_3,			//	102
    SPELL_ENTRY_EffectChainTarget_1,		//	103
    SPELL_ENTRY_EffectChainTarget_2,		//	104
    SPELL_ENTRY_EffectChainTarget_3,		//	105
    SPELL_ENTRY_EffectSpellGroupRelation_1,	//	106
    SPELL_ENTRY_EffectSpellGroupRelation_2,	//	107
    SPELL_ENTRY_EffectSpellGroupRelation_3,	//	108
    SPELL_ENTRY_EffectMiscValue_1,			//	109
    SPELL_ENTRY_EffectMiscValue_2,			//	110
    SPELL_ENTRY_EffectMiscValue_3,			//	111
    SPELL_ENTRY_EffectTriggerSpell_1,		//	112
    SPELL_ENTRY_EffectTriggerSpell_2,		//	113
    SPELL_ENTRY_EffectTriggerSpell_3,		//	114
    SPELL_ENTRY_EffectPointsPerComboPoint_1,//	115
    SPELL_ENTRY_EffectPointsPerComboPoint_2,//	116
    SPELL_ENTRY_EffectPointsPerComboPoint_3,//	117
    SPELL_ENTRY_SpellVisual,				//	118
    SPELL_ENTRY_field114,					//	119
    SPELL_ENTRY_dummy,						//	120
    SPELL_ENTRY_CoSpell,					//	121
    SPELL_ENTRY_spellPriority,				//	122
    SPELL_ENTRY_Name,						//	123
    SPELL_ENTRY_NameAlt1,					//	124
    SPELL_ENTRY_NameAlt2,					//	125
    SPELL_ENTRY_NameAlt3,					//	126
    SPELL_ENTRY_NameAlt4,					//	127
    SPELL_ENTRY_NameAlt5,					//	128
    SPELL_ENTRY_NameAlt6,					//	129
    SPELL_ENTRY_NameAlt7,					//	130
    SPELL_ENTRY_NameAlt8,					//	131
    SPELL_ENTRY_NameAlt9,					//	132
    SPELL_ENTRY_NameAlt10,					//	133
    SPELL_ENTRY_NameAlt11,					//	134
    SPELL_ENTRY_NameAlt12,					//	135
    SPELL_ENTRY_NameAlt13,					//	136
    SPELL_ENTRY_NameAlt14,					//	137
    SPELL_ENTRY_NameAlt15,					//	138
    SPELL_ENTRY_NameFlags,					//	139
    SPELL_ENTRY_Rank,						//	140
    SPELL_ENTRY_RankAlt1,					//	141
    SPELL_ENTRY_RankAlt2,					//	142
    SPELL_ENTRY_RankAlt3,					//	143
    SPELL_ENTRY_RankAlt4,					//	144
    SPELL_ENTRY_RankAlt5,					//	145
    SPELL_ENTRY_RankAlt6,					//	146
    SPELL_ENTRY_RankAlt7,					//	147
    SPELL_ENTRY_RankAlt8,					//	148
    SPELL_ENTRY_RankAlt9,					//	149
    SPELL_ENTRY_RankAlt10,					//	150
    SPELL_ENTRY_RankAlt11,					//	151
    SPELL_ENTRY_RankAlt12,					//	152
    SPELL_ENTRY_RankAlt13,					//	153
    SPELL_ENTRY_RankAlt14,					//	154
    SPELL_ENTRY_RankAlt15,					//	155
    SPELL_ENTRY_RankFlags,					//	156
    SPELL_ENTRY_Description,				//	157
    SPELL_ENTRY_DescriptionAlt1,			//	158
    SPELL_ENTRY_DescriptionAlt2,			//	159
    SPELL_ENTRY_DescriptionAlt3,			//	160
    SPELL_ENTRY_DescriptionAlt4,			//	161
    SPELL_ENTRY_DescriptionAlt5,			//	162
    SPELL_ENTRY_DescriptionAlt6,			//	163
    SPELL_ENTRY_DescriptionAlt7,			//	164
    SPELL_ENTRY_DescriptionAlt8,			//	165
    SPELL_ENTRY_DescriptionAlt9,			//	166
    SPELL_ENTRY_DescriptionAlt10,			//	167
    SPELL_ENTRY_DescriptionAlt11,			//	168
    SPELL_ENTRY_DescriptionAlt12,			//	169
    SPELL_ENTRY_DescriptionAlt13,			//	170
    SPELL_ENTRY_DescriptionAlt14,			//	171
    SPELL_ENTRY_DescriptionAlt15,			//	172
    SPELL_ENTRY_DescriptionFlags,			//	173
    SPELL_ENTRY_BuffDescription,			//	174
    SPELL_ENTRY_BuffDescriptionAlt1,		//	175
    SPELL_ENTRY_BuffDescriptionAlt2,		//	176
    SPELL_ENTRY_BuffDescriptionAlt3,		//	177
    SPELL_ENTRY_BuffDescriptionAlt4,		//	178
    SPELL_ENTRY_BuffDescriptionAlt5,		//	179
    SPELL_ENTRY_BuffDescriptionAlt6,		//	180
    SPELL_ENTRY_BuffDescriptionAlt7,		//	181
    SPELL_ENTRY_BuffDescriptionAlt8,		//	182
    SPELL_ENTRY_BuffDescriptionAlt9,		//	183
    SPELL_ENTRY_BuffDescriptionAlt10,		//	184
    SPELL_ENTRY_BuffDescriptionAlt11,		//	185
    SPELL_ENTRY_BuffDescriptionAlt12,		//	186
    SPELL_ENTRY_BuffDescriptionAlt13,		//	187
    SPELL_ENTRY_BuffDescriptionAlt14,		//	188
    SPELL_ENTRY_BuffDescriptionAlt15,		//	189
    SPELL_ENTRY_buffdescflags,				//	190
    SPELL_ENTRY_ManaCostPercentage,			//	191
    SPELL_ENTRY_unkflags,					//	192
    SPELL_ENTRY_StartRecoveryTime,			//	193
    SPELL_ENTRY_StartRecoveryCategory,		//	194
    SPELL_ENTRY_SpellFamilyName,			//	195
    SPELL_ENTRY_SpellGroupType,				//	196
    SPELL_ENTRY_unkne,						//	197
    SPELL_ENTRY_MaxTargets,					//	198
    SPELL_ENTRY_Spell_Dmg_Type,				//	199
    SPELL_ENTRY_FG,							//	200
    SPELL_ENTRY_FH,							//	201
    SPELL_ENTRY_dmg_multiplier_1,			//	202
    SPELL_ENTRY_dmg_multiplier_2,			//	203
    SPELL_ENTRY_dmg_multiplier_3,			//	204
    SPELL_ENTRY_FL,							//	205
    SPELL_ENTRY_FM,							//	206
    SPELL_ENTRY_FN,							//	207
	SPELL_ENTRY_TotemCategory1,				//	208
	SPELL_ENTRY_TotemCategory2,				//	209
	SPELL_ENTRY_RequiredAreaID				//	210
};

// target type flags
enum SpellTargetTypes
{
    SPELL_TARGET_TYPE_NONE              = 0x01,
    SPELL_TARGET_TYPE_PROFESSION        = 0x02,
    SPELL_TARGET_TYPE_NONE1             = 0x04,
    SPELL_TARGET_TYPE_NONE2             = 0x08,
    SPELL_TARGET_TYPE_ENCHANTABLE_ITEM  = 0x10,
    SPELL_TARGET_TYPE_UNK               = 0x20,     // seems to be scripted stuff
    SPELL_TARGET_TYPE_UNK0              = 0x40,     // lots of spells interesting to research this one further
    SPELL_TARGET_TYPE_UNK1              = 0x80,     // something todo with scripted and GM stuff
    SPELL_TARGET_TYPE_UNK2              = 0x100,    // lots of spells interesting to research this one further...
    SPELL_TARGET_TYPE_PLAYER_CORPSE     = 0x200,
    SPELL_TARGET_TYPE_DEATHx            = 0x400,
    SPELL_TARGET_TYPE_NONE3             = 0x800,
    SPELL_TARGET_TYPE_NONE4             = 0x1000,
    SPELL_TARGET_TYPE_NONE5             = 0x2000,
    SPELL_TARGET_TYPE_GAME_OBJECTS      = 0x4000, // like chests and mining
    SPELL_TARGET_TYPE_DEATH             = 0x8000,
};

enum SpellTypes // SPELL_ENTRY_buffType
{
    SPELL_TYPE_NONE                 = 0x00000000,
    SPELL_TYPE_SEAL                 = 0x00000001,
    SPELL_TYPE_ASPECT               = 0x00000002,
    SPELL_TYPE_BLESSING             = 0x00000004,
    SPELL_TYPE_CURSE                = 0x00000008,
    SPELL_TYPE_STING                = 0x00000010,
    SPELL_TYPE_ARMOR                = 0x00000020,
    SPELL_TYPE_AURA                 = 0x00000040,
    //hmm these could be named simply incompatible spells. One active at a time
    SPELL_TYPE_MARK_GIFT            = 0x00000080,
    SPELL_TYPE_TRACK                = 0x00000100,
    SPELL_TYPE_HUNTER_TRAP          = 0x00000200,
    SPELL_TYPE_MAGE_INTEL           = 0x00000400,
    SPELL_TYPE_MAGE_MAGI            = 0x00000800,
    SPELL_TYPE_MAGE_WARDS           = 0x00001000,
    SPELL_TYPE_PRIEST_SH_PPROT      = 0x00002000,
    SPELL_TYPE_SHIELD               = 0x00004000,
    SPELL_TYPE_FORTITUDE            = 0x00008000,
    SPELL_TYPE_SPIRIT               = 0x00010000,
    SPELL_TYPE_MAGE_AMPL_DUMP       = 0x00020000,
    SPELL_TYPE_WARLOCK_IMMOLATE     = 0x00040000, //maybe there is a better way to trigger the aura state for immolate spell
    SPELL_TYPE_ELIXIR_BATTLE		= 0x00080000, 
    SPELL_TYPE_ELIXIR_GUARDIAN      = 0x00100000, 
    SPELL_TYPE_ELIXIR_FLASK         = SPELL_TYPE_ELIXIR_BATTLE | SPELL_TYPE_ELIXIR_GUARDIAN, //weee, this contains both battle and guardian elixirs ;)
    SPELL_TYPE_HUNTER_MARK			= 0x00200000,
    SPELL_TYPE_WARRIOR_SHOUT        = 0x00400000,
};

//custom stuff generated for spells that will not change in time
enum SpellIsFlags
{
    SPELL_FLAG_IS_DAMAGING				= 0x00000001,
    SPELL_FLAG_IS_HEALING				= 0x00000002,
    SPELL_FLAG_IS_TARGETINGSTEALTHED	= 0x00000004,
    SPELL_FLAG_IS_REQUIRECOOLDOWNUPDATE	= 0x00000008, //it started with rogue cold blood but i'm sure others will come
    SPELL_FLAG_IS_POISON				= 0x00000010, //rogue has a few spells that can stack so can't use the spell_type enum ;)
    SPELL_FLAG_IS_FINISHING_MOVE		= 0x00000020, //rogue has a few spells that can stack so can't use the spell_type enum ;)
    SPELL_FLAG_IS_NOT_USING_DMG_BONUS	= 0x00000040, 
    SPELL_FLAG_IS_CHILD_SPELL			= 0x00000080, //auras proc auras that have same name, these should not remove mother aura when adding to target
    SPELL_FLAG_IS_CASTED_ON_PET_SUMMON_ON_PET		= 0x00000100, //we should cast these on pet too
    SPELL_FLAG_IS_CASTED_ON_PET_SUMMON_PET_OWNER	= 0x00000200, //we should cast these on owner too
    SPELL_FLAG_IS_EXPIREING_WITH_PET	= 0x00000400, //when pet dies, we remove this too
    SPELL_FLAG_IS_EXPIREING_ON_PET		= 0x00000800, //when pet is summoned
};

enum SpellCoefficientsFlags
{
	SPELL_FLAG_IS_DOT_OR_HOT_SPELL		= 0x00000001, //Damage over Time or Healing over Time Spells
	SPELL_FLAG_IS_DD_OR_DH_SPELL		= 0x00000002, //Direct Damage or Direct Healing Spells
	SPELL_FLAG_IS_DD_DH_DOT_SPELL		= SPELL_FLAG_IS_DOT_OR_HOT_SPELL | SPELL_FLAG_IS_DD_OR_DH_SPELL, //DoT+(DD|DH) Spells
	SPELL_FLAG_AOE_SPELL				= 0x00000004, //AoE Spells
	SPELL_FLAG_ADITIONAL_EFFECT			= 0x00000008, //Spells with aditional effect not DD or DoT or HoT
};

ASCENT_INLINE bool CanAgroHash(uint32 spellhashname)
{
    if (spellhashname == 4287212498UL) //hunter's mark
        return false;
    else
        return true;
}

/************************************************************************/
/* IsDamagingSpell, this function seems slow, its only used rarely      */
/************************************************************************/
ASCENT_INLINE bool IsDamagingSpell(SpellEntry *sp)
{
    switch (sp->Effect[0])
    {
        case SPELL_EFFECT_SCHOOL_DAMAGE:
        case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
        case SPELL_EFFECT_ADD_EXTRA_ATTACKS:
        case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
        case SPELL_EFFECT_POWER_BURN:
        case SPELL_EFFECT_ATTACK:
            return true;
    }
    switch (sp->Effect[1])
    {
        case SPELL_EFFECT_SCHOOL_DAMAGE:
        case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
        case SPELL_EFFECT_ADD_EXTRA_ATTACKS:
        case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
        case SPELL_EFFECT_POWER_BURN:
        case SPELL_EFFECT_ATTACK:
            return true;
    }
    switch (sp->Effect[2])
    {
        case SPELL_EFFECT_SCHOOL_DAMAGE:
        case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
        case SPELL_EFFECT_ADD_EXTRA_ATTACKS:
        case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
        case SPELL_EFFECT_POWER_BURN:
        case SPELL_EFFECT_ATTACK:
            return true;
    }
    if( sp->Effect[0]==SPELL_EFFECT_APPLY_AURA ||
       sp->Effect[0]==SPELL_EFFECT_APPLY_AREA_AURA)
    {
        switch (sp->EffectApplyAuraName[0])
        {
            case 3://SPELL_AURA_PERIODIC_DAMAGE:
            case 43://SPELL_AURA_PROC_TRIGGER_DAMAGE:
            case 89://SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
            case 162://SPELL_AURA_POWER_BURN:
                return true;
        }
    }
    if( sp->Effect[1]==SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[1]==SPELL_EFFECT_APPLY_AREA_AURA)
    {
        switch (sp->EffectApplyAuraName[1])
        {
            case 3://SPELL_AURA_PERIODIC_DAMAGE:
            case 43://SPELL_AURA_PROC_TRIGGER_DAMAGE:
            case 89://SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
            case 162://SPELL_AURA_POWER_BURN:
                return true;
        }
    }
    if( sp->Effect[2]==SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[2]==SPELL_EFFECT_APPLY_AREA_AURA)
    {
        switch (sp->EffectApplyAuraName[2])
        {
            case 3://SPELL_AURA_PERIODIC_DAMAGE:
            case 43://SPELL_AURA_PROC_TRIGGER_DAMAGE:
            case 89://SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
            case 162://SPELL_AURA_POWER_BURN:
                return true;
        }
    }
    return false;
}

ASCENT_INLINE bool IsHealingSpell(SpellEntry *sp)
{
    switch( sp->Effect[0] )
    {
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_HEAL:
        case SPELL_EFFECT_HEALTH_FUNNEL:
        case SPELL_EFFECT_HEAL_MAX_HEALTH:
            return true;
		default: break;
    }
    switch( sp->Effect[1] )
    {
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_HEAL:
        case SPELL_EFFECT_HEALTH_FUNNEL:
        case SPELL_EFFECT_HEAL_MAX_HEALTH:
            return true;
		default: break;
    }
    switch( sp->Effect[2] )
    {
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_HEAL:
        case SPELL_EFFECT_HEALTH_FUNNEL:
        case SPELL_EFFECT_HEAL_MAX_HEALTH:
            return true;
		default: break;
    }
    if( sp->Effect[0] == SPELL_EFFECT_APPLY_AURA ||
		sp->Effect[0] == SPELL_EFFECT_APPLY_AREA_AURA )
    {
        switch( sp->EffectApplyAuraName[0] )
        {
            case 8://SPELL_AURA_PERIODIC_HEAL:
            case 62://SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
                return true;
			default: break;
        }
    }
    if( sp->Effect[1] == SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[1] == SPELL_EFFECT_APPLY_AREA_AURA )
    {
        switch (sp->EffectApplyAuraName[1])
        {
            case 8://SPELL_AURA_PERIODIC_HEAL:
            case 62://SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
                return true;
			default: break;
        }
    }
    if( sp->Effect[2] == SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[2] == SPELL_EFFECT_APPLY_AREA_AURA )
    {
        switch( sp->EffectApplyAuraName[2] )
        {
            case 8://SPELL_AURA_PERIODIC_HEAL:
            case 62://SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
                return true;
			default: break;
        }
    }
	//flash of light, holy light uses scripted effect which is not neceserally heal spell
	if( sp->NameHash == SPELL_HASH_HOLY_LIGHT || sp->NameHash == SPELL_HASH_FLASH_OF_LIGHT  )
		return true;
	
    return false;
}

ASCENT_INLINE bool IsInrange(LocationVector & location, Object * o, float square_r)
{
    float r = o->GetDistanceSq(location);
    return ( r<=square_r);
}

ASCENT_INLINE bool IsInrange(float x1,float y1, float z1, Object * o,float square_r)
{
    float r = o->GetDistanceSq(x1, y1, z1);
    return ( r<=square_r);
}

ASCENT_INLINE bool IsInrange(float x1,float y1, float z1,float x2,float y2, float z2,float square_r)
{
    float t;
    float r;
    t=x1-x2;
    r=t*t;
    t=y1-y2;
    r+=t*t;
    t=z1-z2;
    r+=t*t;
    return ( r<=square_r);
}
   
ASCENT_INLINE bool IsInrange(Object * o1,Object * o2,float square_r)
{
    return IsInrange(o1->GetPositionX(),o1->GetPositionY(),o1->GetPositionZ(),
        o2->GetPositionX(),o2->GetPositionY(),o2->GetPositionZ(),square_r);
}

ASCENT_INLINE bool TargetTypeCheck(Object *obj,uint32 ReqCreatureTypeMask)
{
	if( !ReqCreatureTypeMask )
		return true;

	if( obj->GetTypeId() == TYPEID_UNIT )
	{
		CreatureInfo* inf = static_cast< Creature* >( obj )->GetCreatureName();
		if( inf == NULL || !( 1 << ( inf->Type - 1 ) & ReqCreatureTypeMask ) )
			return false;
	}
	else if(obj->GetTypeId() == TYPEID_PLAYER && !(UNIT_TYPE_HUMANOID_BIT & ReqCreatureTypeMask))
		return false;
	else return false;//omg, how in the hack did we cast it on a GO ? But who cares ?
	return true;
}

class SpellCastTargets
{
public:
    void read ( WorldPacket & data,uint64 caster );
    void write ( WorldPacket & data);

    SpellCastTargets() : m_targetMask(0), m_targetMaskExtended(0), m_unitTarget(0), m_itemTarget(0), m_srcX(0), m_srcY(0), m_srcZ(0),
        m_destX(0), m_destY(0), m_destZ(0) {}

    SpellCastTargets(uint16 TargetMask, uint64 unitTarget, uint64 itemTarget, float srcX, float srcY,
        float srcZ, float destX, float destY, float destZ) : m_targetMask(TargetMask), m_targetMaskExtended(0), m_unitTarget(unitTarget),
        m_itemTarget(itemTarget), m_srcX(srcX), m_srcY(srcY), m_srcZ(srcZ), m_destX(destX), m_destY(destY), m_destZ(destZ) {}

    SpellCastTargets(uint64 unitTarget) : m_targetMask(0x2), m_targetMaskExtended(0), m_unitTarget(unitTarget), m_itemTarget(0),
        m_srcX(0), m_srcY(0), m_srcZ(0), m_destX(0), m_destY(0), m_destZ(0) {}

    SpellCastTargets(WorldPacket & data, uint64 caster) : m_targetMask(0), m_targetMaskExtended(0), m_unitTarget(0), m_itemTarget(0), m_srcX(0), m_srcY(0), m_srcZ(0),
        m_destX(0), m_destY(0), m_destZ(0)
    {
        read(data, caster);
    }

    SpellCastTargets& operator=(const SpellCastTargets &target)
    {
        m_unitTarget = target.m_unitTarget;
        m_itemTarget = target.m_itemTarget;

        m_srcX = target.m_srcX;
        m_srcY = target.m_srcY;
        m_srcZ = target.m_srcZ;

        m_destX = target.m_destX;
        m_destY = target.m_destY;
        m_destZ = target.m_destZ;

        m_strTarget = target.m_strTarget;

        m_targetMask = target.m_targetMask;
	m_targetMaskExtended = target.m_targetMaskExtended;

        return *this;
    }

    uint16 m_targetMask;
    uint16 m_targetMaskExtended;			// this could be a 32 also
    uint64 m_unitTarget;
    uint64 m_itemTarget;
    float m_srcX, m_srcY, m_srcZ;
    float m_destX, m_destY, m_destZ;
    std::string m_strTarget;

};

enum SpellState
{
    SPELL_STATE_NULL      = 0,
    SPELL_STATE_PREPARING = 1,
    SPELL_STATE_CASTING   = 2,
    SPELL_STATE_FINISHED  = 3,
    SPELL_STATE_IDLE      = 4
};

enum ShapeshiftForm
{
	FORM_NORMAL             = 0,
	FORM_CAT                = 1,
	FORM_TREE               = 2,
	FORM_TRAVEL             = 3,
	FORM_AQUA               = 4,
	FORM_BEAR               = 5,
	FORM_AMBIENT            = 6,
	FORM_GHOUL              = 7,
	FORM_DIREBEAR           = 8,
	FORM_CREATUREBEAR       = 14,
	FORM_GHOSTWOLF          = 16,
	FORM_BATTLESTANCE       = 17,
	FORM_DEFENSIVESTANCE    = 18,
	FORM_BERSERKERSTANCE    = 19,
	FORM_SWIFT              = 27,
	FORM_SHADOW             = 28,
	FORM_FLIGHT             = 29,
	FORM_STEALTH            = 30,
	FORM_MOONKIN            = 31,
	FORM_SPIRITOFREDEMPTION = 32,
};

enum DISPEL_TYPE
{
    DISPEL_ZGTRINKETS = -1,
    DISPEL_NULL,
    DISPEL_MAGIC,
    DISPEL_CURSE,
    DISPEL_DISEASE,
    DISPEL_POISON,
    DISPEL_STEALTH,
    DISPEL_INVISIBILTY,
    DISPEL_ALL,
    DISPEL_SPECIAL_NPCONLY,
    DISPEL_FRENZY,
};

enum DISPEL_MECHANIC_TYPE
{
    DISPEL_MECHANIC_CHARM       = 1,
    DISPEL_MECHANIC_FEAR        = 5,
    DISPEL_MECHANIC_ROOT        = 7,
    DISPEL_MECHANIC_SLEEP       = 10,
    DISPEL_MECHANIC_SNARE       = 11,
    DISPEL_MECHANIC_STUN        = 12,
    DISPEL_MECHANIC_KNOCKOUT    = 14,
    DISPEL_MECHANIC_BLEED       = 15,
    DISPEL_MECHANIC_POLYMORPH   = 17,
    DISPEL_MECHANIC_BANISH      = 18,
    DISPEL_MECHANIC_MOUNTED     = 21,
};
enum MECHANICS
{
    MECHANIC_CHARMED = 1,
    MECHANIC_DISORIENTED, // 2
    MECHANIC_DISARMED, // 3
    MECHANIC_DISTRACED, // 4
    MECHANIC_FLEEING, // 5
    MECHANIC_CLUMSY, // 6
    MECHANIC_ROOTED, // 7
    MECHANIC_PACIFIED, // 8
    MECHANIC_SILENCED, // 9
    MECHANIC_ASLEEP, // 10
    MECHANIC_ENSNARED, // 11
    MECHANIC_STUNNED,
    MECHANIC_FROZEN,
    MECHANIC_INCAPACIPATED,
    MECHANIC_BLEEDING,
    MECHANIC_HEALING,
    MECHANIC_POLYMORPHED,
    MECHANIC_BANISHED,
    MECHANIC_SHIELDED,
    MECHANIC_SHACKLED,
    MECHANIC_MOUNTED,
    MECHANIC_SEDUCED,
    MECHANIC_TURNED,
    MECHANIC_HORRIFIED,
    MECHANIC_INVULNARABLE,
    MECHANIC_INTERRUPTED,
    MECHANIC_DAZED
};

typedef enum {
   EFF_TARGET_NONE										= 0,
   EFF_TARGET_SELF										= 1,
   EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS		= 3,
   EFF_TARGET_PET										= 5,
   EFF_TARGET_SINGLE_ENEMY								= 6,
   EFF_TARGET_SCRIPTED_TARGET							= 7,
   EFF_TARGET_ALL_TARGETABLE_AROUND_LOCATION_IN_RADIUS  = 8,
   EFF_TARGET_HEARTSTONE_LOCATION						= 9,
   EFF_TARGET_ALL_ENEMY_IN_AREA							= 15,
   EFF_TARGET_ALL_ENEMY_IN_AREA_INSTANT					= 16,
   EFF_TARGET_TELEPORT_LOCATION							= 17,
   EFF_TARGET_LOCATION_TO_SUMMON						= 18,
   EFF_TARGET_ALL_PARTY_AROUND_CASTER					= 20,
   EFF_TARGET_SINGLE_FRIEND								= 21,
   EFF_TARGET_ALL_ENEMIES_AROUND_CASTER					= 22,
   EFF_TARGET_GAMEOBJECT								= 23,
   EFF_TARGET_IN_FRONT_OF_CASTER						= 24,
   EFF_TARGET_DUEL										= 25,//Dont know the real name!!!
   EFF_TARGET_GAMEOBJECT_ITEM							= 26,
   EFF_TARGET_PET_MASTER								= 27,
   EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED				= 28,
   EFF_TARGET_ALL_PARTY_IN_AREA_CHANNELED				= 29,
   EFF_TARGET_ALL_FRIENDLY_IN_AREA						= 30,
   EFF_TARGET_ALL_TARGETABLE_AROUND_LOCATION_IN_RADIUS_OVER_TIME	= 31,
   EFF_TARGET_MINION									= 32,
   EFF_TARGET_ALL_PARTY_IN_AREA							= 33,
   EFF_TARGET_SINGLE_PARTY								= 35,
   EFF_TARGET_PET_SUMMON_LOCATION						= 36,
   EFF_TARGET_ALL_PARTY									= 37,
   EFF_TARGET_SCRIPTED_OR_SINGLE_TARGET					= 38,
   EFF_TARGET_SELF_FISHING								= 39,
   EFF_TARGET_SCRIPTED_GAMEOBJECT						= 40,
   EFF_TARGET_TOTEM_EARTH								= 41,
   EFF_TARGET_TOTEM_WATER								= 42,
   EFF_TARGET_TOTEM_AIR									= 43,
   EFF_TARGET_TOTEM_FIRE								= 44,
   EFF_TARGET_CHAIN										= 45,
   EFF_TARGET_SCIPTED_OBJECT_LOCATION					= 46,
   EFF_TARGET_DYNAMIC_OBJECT							= 47,//not sure exactly where is used
   EFF_TARGET_MULTIPLE_SUMMON_LOCATION					= 48,
   EFF_TARGET_MULTIPLE_SUMMON_PET_LOCATION				= 49,
   EFF_TARGET_SUMMON_LOCATION							= 50,
   EFF_TARGET_CALIRI_EGS								= 51,
   EFF_TARGET_LOCATION_NEAR_CASTER						= 52,
   EFF_TARGET_CURRENT_SELECTION							= 53,
   EFF_TARGET_TARGET_AT_ORIENTATION_TO_CASTER			= 54,
   EFF_TARGET_LOCATION_INFRONT_CASTER					= 55,
   EFF_TARGET_PARTY_MEMBER								= 57,
   EFF_TARGET_TARGET_FOR_VISUAL_EFFECT					= 59,
   EFF_TARGET_SCRIPTED_TARGET2							= 60,
   EFF_TARGET_AREAEFFECT_PARTY_AND_CLASS				= 61,
   EFF_TARGET_PRIEST_CHAMPION							= 62, //wtf ?
   EFF_TARGET_NATURE_SUMMON_LOCATION					= 63, 
   EFF_TARGET_BEHIND_TARGET_LOCATION					= 65, 
   EFF_TARGET_MULTIPLE_GUARDIAN_SUMMON_LOCATION			= 72,
   EFF_TARGET_NETHETDRAKE_SUMMON_LOCATION				= 73,
   EFF_TARGET_SCRIPTED_LOCATION							= 74,
   EFF_TARGET_LOCATION_INFRONT_CASTER_AT_RANGE			= 75,
   EFF_TARGET_ENEMYS_IN_ARE_CHANNELED_WITH_EXCEPTIONS	= 76,
   EFF_TARGET_SELECTED_ENEMY_CHANNELED					= 77,
   EFF_TARGET_SELECTED_ENEMY_DEADLY_POISON				= 86,
} SpellEffectTarget;


ASCENT_INLINE bool IsTargetingStealthed(SpellEntry *sp)
{
	if(
		sp->EffectImplicitTargetA[0]==EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS ||
		sp->EffectImplicitTargetA[1]==EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS ||
		sp->EffectImplicitTargetA[2]==EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS ||
		sp->EffectImplicitTargetB[0]==EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS ||
		sp->EffectImplicitTargetB[1]==EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS ||
		sp->EffectImplicitTargetB[2]==EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS ||
		sp->EffectImplicitTargetA[0]==EFF_TARGET_ALL_ENEMIES_AROUND_CASTER ||
		sp->EffectImplicitTargetA[1]==EFF_TARGET_ALL_ENEMIES_AROUND_CASTER ||
		sp->EffectImplicitTargetA[2]==EFF_TARGET_ALL_ENEMIES_AROUND_CASTER ||
		sp->EffectImplicitTargetB[0]==EFF_TARGET_ALL_ENEMIES_AROUND_CASTER ||
		sp->EffectImplicitTargetB[1]==EFF_TARGET_ALL_ENEMIES_AROUND_CASTER ||
		sp->EffectImplicitTargetB[2]==EFF_TARGET_ALL_ENEMIES_AROUND_CASTER ||
		sp->EffectImplicitTargetA[0]==EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED ||
		sp->EffectImplicitTargetA[1]==EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED ||
		sp->EffectImplicitTargetA[2]==EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED ||
		sp->EffectImplicitTargetB[0]==EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED ||
		sp->EffectImplicitTargetB[1]==EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED ||
		sp->EffectImplicitTargetB[2]==EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED
		)
		return 1;
	return 0;
}

// slow
struct SpellTargetMod
{
    SpellTargetMod(uint64 _TargetGuid, uint8 _TargetModType) : TargetGuid(_TargetGuid), TargetModType(_TargetModType)
    {

    }
    uint64 TargetGuid;
    uint8  TargetModType;
};


typedef std::vector<uint64> TargetsList;
typedef std::vector<SpellTargetMod> SpellTargetsList;

typedef void(Spell::*pSpellEffect)(uint32 i);
typedef void(Spell::*pSpellTarget)(uint32 i, uint32 j);

#define POWER_TYPE_HEALTH -2
#define POWER_TYPE_MANA 0
#define POWER_TYPE_RAGE 1
#define POWER_TYPE_FOCUS 2
#define POWER_TYPE_ENERGY 3
// we have power type 15 and 31 :S

#define GO_FISHING_BOBBER 35591

#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000
class DummySpellHandler;

enum SpellDidHitResult
{
	SPELL_DID_HIT_SUCCESS					= 0,
	SPELL_DID_HIT_MISS						= 1,
	SPELL_DID_HIT_RESIST					= 2,
	SPELL_DID_HIT_DODGE						= 3,
	SPELL_DID_HIT_DEFLECT					= 4,
	SPELL_DID_HIT_BLOCK						= 5,
	SPELL_DID_HIT_EVADE						= 6,
	SPELL_DID_HIT_IMMUNE					= 7,
};

// Spell instance
class SERVER_DECL Spell
{
public:
    friend class DummySpellHandler;
    Spell( Object* Caster, SpellEntry *info, bool triggered, Aura* aur);
    ~Spell();

    // Fills specified targets at the area of effect
    void FillSpecifiedTargetsInArea(float srcx,float srcy,float srcz,uint32 ind, uint32 specification);
    // Fills specified targets at the area of effect. We suppose we already inited this spell and know the details
    void FillSpecifiedTargetsInArea(uint32 i,float srcx,float srcy,float srcz, float range, uint32 specification);
    // Fills the targets at the area of effect
    void FillAllTargetsInArea(uint32 i, float srcx,float srcy,float srcz, float range);
    // Fills the targets at the area of effect. We suppose we already inited this spell and know the details
    void FillAllTargetsInArea(float srcx,float srcy,float srcz,uint32 ind);
    // Fills the targets at the area of effect. We suppose we already inited this spell and know the details
    void FillAllTargetsInArea(LocationVector & location,uint32 ind);
    // Fills the targets at the area of effect. We suppose we already inited this spell and know the details
    void FillAllFriendlyInArea(uint32 i, float srcx,float srcy,float srcz, float range);
    //get single Enemy as target
    uint64 GetSinglePossibleEnemy(uint32 i, float prange=0);
    //get single Enemy as target
    uint64 GetSinglePossibleFriend(uint32 i, float prange=0);
    //generate possible target list for a spell. Use as last resort since it is not acurate
    void GenerateTargets(SpellCastTargets *store_buff);
    // Fills the target map of the spell packet
    void FillTargetMap(uint32);
    // See if we hit the target or can it resist (evade/immune/resist on spellgo) (0=success)
    uint8 DidHit(uint32 effindex,Unit* target);
    // Prepares the spell thats going to cast to targets
    uint8 prepare(SpellCastTargets * targets);
    // Cancels the current spell
    void cancel();
    // Update spell state based on time difference
    void update(uint32 difftime);
    // Casts the spell
    void cast(bool);
    // Finishes the casted spell
    void finish();
    // Handle the Effects of the Spell
    void HandleEffects(uint64 guid,uint32 i);
    // Take Power from the caster based on spell power usage
    bool TakePower();
    // Has power?
    bool HasPower();
    // Trigger Spell function that triggers triggered spells
    void TriggerSpell();
    // Checks the caster is ready for cast
    uint8 CanCast(bool);
    // Removes reagents, ammo, and items/charges
    void RemoveItems();
    // Calculates the i'th effect value
    int32 CalculateEffect(uint32, Unit *target);
    // Handles Teleport function
    void HandleTeleport(uint32 id, Unit* Target);
    // Determines how much skill caster going to gain
    void DetermineSkillUp();
    // Increases cast time of the spell
    void AddTime(uint32 type);
    void AddCooldown();
    void AddStartCooldown();


    bool Reflect(Unit * refunit);

    ASCENT_INLINE uint32 getState() { return m_spellState; }
    ASCENT_INLINE void SetUnitTarget(Unit *punit){unitTarget=punit;}

    // Send Packet functions
    void SendCastResult(uint8 result);
    void SendSpellStart();
    void SendSpellGo();
    void SendLogExecute(uint32 damage, uint64 & targetGuid);
    void SendInterrupted(uint8 result);
    void SendChannelUpdate(uint32 time);
    void SendChannelStart(uint32 duration);
    void SendResurrectRequest(Player* target);
    void SendHealSpellOnPlayer(Object* caster, Object* target, uint32 dmg,bool critical);
    void SendHealManaSpellOnPlayer(Object * caster, Object * target, uint32 dmg, uint32 powertype);
    

    void HandleAddAura(uint64 guid);
    void writeSpellGoTargets( WorldPacket * data );
    void writeSpellMissedTargets( WorldPacket * data );

    SpellEntry* m_spellInfo;
    uint32 pSpellId;
    SpellEntry *ProcedOnSpell; //some spells need to know the origins of the proc too
    SpellCastTargets m_targets;

    void CreateItem(uint32 itemId);

    // Effect Handlers
    void SpellEffectNULL(uint32 i);
    void SpellEffectInstantKill(uint32 i);
    void SpellEffectSchoolDMG(uint32 i);
    void SpellEffectDummy(uint32 i);
    void SpellEffectTeleportUnits(uint32 i);
    void SpellEffectApplyAura(uint32 i);
    void SpellEffectPowerDrain(uint32 i);
    void SpellEffectHealthLeech(uint32 i);
    void SpellEffectHeal(uint32 i);
    void SpellEffectQuestComplete(uint32 i);
    void SpellEffectWeapondamageNoschool(uint32 i);
    void SpellEffectResurrect(uint32 i);
    void SpellEffectAddExtraAttacks(uint32 i);
    void SpellEffectDodge(uint32 i);
    void SpellEffectBlock(uint32 i);
    void SpellEffectParry(uint32 i);
    void SpellEffectCreateItem(uint32 i);
    void SpellEffectPersistentAA(uint32 i);
    void SpellEffectSummon(uint32 i);
    void SpellEffectLeap(uint32 i);
    void SpellEffectEnergize(uint32 i);
    void SpellEffectWeaponDmgPerc(uint32 i);
    void SpellEffectTriggerMissile(uint32 i);
    void SpellEffectOpenLock(uint32 i);
    void SpellEffectApplyAA(uint32 i);
    void SpellEffectLearnSpell(uint32 i);
    void SpellEffectSpellDefense(uint32 i);
    void SpellEffectDispel(uint32 i);
    void SpellEffectSummonWild(uint32 i);
    void SpellEffectSummonGuardian(uint32 i);
    void SpellEffectSkillStep(uint32 i);
    void SpellEffectSummonObject(uint32 i);
    void SpellEffectEnchantItem(uint32 i);
    void SpellEffectEnchantItemTemporary(uint32 i);
    void SpellEffectTameCreature(uint32 i);
    void SpellEffectSummonPet(uint32 i);
    void SpellEffectWeapondamage(uint32 i);
    void SpellEffectPowerBurn(uint32 i);
    void SpellEffectThreat(uint32 i);
    void SpellEffectTriggerSpell(uint32 i);
    void SpellEffectHealthFunnel(uint32 i);
    void SpellEffectPowerFunnel(uint32 i);
    void SpellEffectHealMaxHealth(uint32 i);
    void SpellEffectInterruptCast(uint32 i);
    void SpellEffectDistract(uint32 i);
    void SpellEffectPickpocket(uint32 i);
    void SpellEffectAddFarsight(uint32 i);
    void SpellEffectSummonPossessed(uint32 i);
    void SpellEffectCreateSummonTotem(uint32 i);
    void SpellEffectHealMechanical(uint32 i);
    void SpellEffectSummonObjectWild(uint32 i);
    void SpellEffectScriptEffect(uint32 i);
    void SpellEffectSanctuary(uint32 i);
    void SpellEffectAddComboPoints(uint32 i);
	void SpellEffectCreateHouse(uint32 i);
    void SpellEffectDuel(uint32 i);
    void SpellEffectStuck(uint32 i);
    void SpellEffectSummonPlayer(uint32 i);
    void SpellEffectActivateObject(uint32 i);
    void SpellEffectSummonTotem(uint32 i);
    void SpellEffectProficiency(uint32 i);
    void SpellEffectSendEvent(uint32 i);
    void SpellEffectSkinning(uint32 i);
    void SpellEffectCharge(uint32 i);
    void SpellEffectSummonCritter(uint32 i);
    void SpellEffectKnockBack(uint32 i);
    void SpellEffectInebriate(uint32 i);
    void SpellEffectFeedPet(uint32 i);
    void SpellEffectDismissPet(uint32 i);
    void SpellEffectReputation(uint32 i);
    void SpellEffectSummonObjectSlot(uint32 i);
    void SpellEffectDispelMechanic(uint32 i);
    void SpellEffectSummonDeadPet(uint32 i);
    void SpellEffectDestroyAllTotems(uint32 i);
    void SpellEffectSummonDemon(uint32 i);
    void SpellEffectAttackMe(uint32 i);
    void SpellEffectSkill(uint32 i);
    void SpellEffectApplyPetAura(uint32 i);
    void SpellEffectDummyMelee(uint32 i);
    void SpellEffectPlayerPull( uint32 i );
    void SpellEffectSpellSteal(uint32 i);
    void SpellEffectProspecting(uint32 i);
    void SpellEffectOpenLockItem(uint32 i);
    void SpellEffectSelfResurrect(uint32 i);
    void SpellEffectDisenchant(uint32 i);
    void SpellEffectWeapon(uint32 i);
    void SpellEffectDefense(uint32 i);
    void SpellEffectDualWield(uint32 i);
    void SpellEffectSkinPlayerCorpse(uint32 i);
    void SpellEffectResurrectNew(uint32 i);
    void SpellEffectTranformItem(uint32);
    void SpellEffectEnvironmentalDamage(uint32);
    void SpellEffectLearnPetSpell(uint32 i);
    void SpellEffectEnchantHeldItem(uint32 i);
    void SpellEffectAddHonor(uint32 i);
    void SpellEffectSpawn(uint32 i);
    void SpellEffectApplyAura128(uint32 i);
	void SpellEffectFlightPath(uint32 i);

    // Spell Targets Handlers
    void SpellTargetNULL(uint32 i, uint32 j);
    void SpellTargetDefault(uint32 i, uint32 j);
    void SpellTargetSelf(uint32 i, uint32 j);
    void SpellTargetInvisibleAOE(uint32 i, uint32 j);
    void SpellTargetFriendly(uint32 i, uint32 j);
    void SpellTargetPet(uint32 i, uint32 j);
    void SpellTargetSingleTargetEnemy(uint32 i, uint32 j);
    void SpellTargetCustomAreaOfEffect(uint32 i, uint32 j);
    void SpellTargetAreaOfEffect(uint32 i, uint32 j);
    void SpellTargetLandUnderCaster(uint32 i, uint32 j); /// I don't think this is the correct name for this one
    void SpellTargetAllPartyMembersRangeNR(uint32 i, uint32 j);
    void SpellTargetSingleTargetFriend(uint32 i, uint32 j);
    void SpellTargetAoE(uint32 i, uint32 j); // something special
    void SpellTargetSingleGameobjectTarget(uint32 i, uint32 j);
    void SpellTargetInFrontOfCaster(uint32 i, uint32 j);
    void SpellTargetSingleFriend(uint32 i, uint32 j);
    void SpellTargetGameobject_itemTarget(uint32 i, uint32 j);
    void SpellTargetPetOwner(uint32 i, uint32 j);
    void SpellTargetEnemysAreaOfEffect(uint32 i, uint32 j);
    void SpellTargetTypeTAOE(uint32 i, uint32 j);
    void SpellTargetAllyBasedAreaEffect(uint32 i, uint32 j);
    void SpellTargetScriptedEffects(uint32 i, uint32 j);
    void SpellTargetSummon(uint32 i, uint32 j);
    void SpellTargetNearbyPartyMembers(uint32 i, uint32 j);
    void SpellTargetSingleTargetPartyMember(uint32 i, uint32 j);
    void SpellTargetScriptedEffects2(uint32 i, uint32 j);
    void SpellTargetPartyMember(uint32 i, uint32 j);
    void SpellTargetDummyTarget(uint32 i, uint32 j);
    void SpellTargetFishing(uint32 i, uint32 j);
    void SpellTargetType40(uint32 i, uint32 j);
    void SpellTargetTotem(uint32 i, uint32 j);
    void SpellTargetChainTargeting(uint32 i, uint32 j);
    void SpellTargetSimpleTargetAdd(uint32 i, uint32 j);
    void SpellTarget56(uint32 o, uint32 j);
    void SpellTargetTargetAreaSelectedUnit(uint32 i, uint32 j);
    void SpellTargetInFrontOfCaster2(uint32 i, uint32 j);
    void SpellTargetTargetPartyMember(uint32 i, uint32 j);
    void SpellTargetSameGroupSameClass(uint32 i, uint32 j);

    void Heal(int32 amount);

    GameObject*		g_caster;
    Unit*			u_caster;
    Item*			i_caster;
    Player*			p_caster;
    Object*			m_caster;

    // 15007 = resurecting sickness
	
	// This returns SPELL_ENTRY_Spell_Dmg_Type where 0 = SPELL_DMG_TYPE_NONE, 1 = SPELL_DMG_TYPE_MAGIC, 2 = SPELL_DMG_TYPE_MELEE, 3 = SPELL_DMG_TYPE_RANGED
	// It should NOT be used for weapon_damage_type which needs: 0 = MELEE, 1 = OFFHAND, 2 = RANGED
	ASCENT_INLINE uint32 GetType() { return ( m_spellInfo->Spell_Dmg_Type == SPELL_DMG_TYPE_NONE ? SPELL_DMG_TYPE_MAGIC : m_spellInfo->Spell_Dmg_Type ); }

    std::vector<uint64> UniqueTargets;
    SpellTargetsList    ModeratedTargets;

    ASCENT_INLINE Item* GetItemTarget() { return itemTarget; }
    ASCENT_INLINE Unit* GetUnitTarget() { return unitTarget; }
    ASCENT_INLINE Player* GetPlayerTarget() { return playerTarget; }
    ASCENT_INLINE GameObject* GetGameObjectTarget() { return gameObjTarget; }

    uint32 chaindamage;
    // -------------------------------------------

    bool IsAspect();
    bool IsSeal();

    uint32 GetDuration()
    {
        if(bDurSet)return Dur;
        bDurSet=true;
        int32 c_dur = 0;

        if(m_spellInfo->DurationIndex)
        {
            SpellDuration *sd=dbcSpellDuration.LookupEntry(m_spellInfo->DurationIndex);
            if(sd)
            {
                //check for negative and 0 durations.
                //duration affected by level
                if((int32)sd->Duration1 < 0 && sd->Duration2 && u_caster)
                {
                    this->Dur = uint32(((int32)sd->Duration1 + (sd->Duration2 * u_caster->getLevel())));
                    if((int32)this->Dur > 0 && sd->Duration3 > 0 && (int32)this->Dur > (int32)sd->Duration3)
                    {
                        this->Dur = sd->Duration3;
                    }

                    if((int32)this->Dur < 0)
						this->Dur = 0;
					c_dur = this->Dur;
                }
                if(sd->Duration1 >= 0 && !c_dur)
                {
                    this->Dur = sd->Duration1;
                }
                //combo point lolerCopter? ;P
                if(p_caster)  
                {
                    uint32 cp=p_caster->m_comboPoints;
                    if(cp)
                    {
                        uint32 bonus=(cp*(sd->Duration3-sd->Duration1))/5;
                        if(bonus)
                        {
                            this->Dur+=bonus;
                            m_requiresCP=true;
                        }
                    }
                }

                if(m_spellInfo->SpellGroupType && u_caster)
                {
                    SM_FIValue(u_caster->SM_FDur,(int32*)&this->Dur,m_spellInfo->SpellGroupType);
                    SM_PIValue(u_caster->SM_PDur,(int32*)&this->Dur,m_spellInfo->SpellGroupType);
#ifdef COLLECTION_OF_UNTESTED_STUFF_AND_TESTERS
					int spell_flat_modifers=0;
					int spell_pct_modifers=0;
					SM_FIValue(u_caster->SM_FDur,&spell_flat_modifers,m_spellInfo->SpellGroupType);
					SM_FIValue(u_caster->SM_PDur,&spell_pct_modifers,m_spellInfo->SpellGroupType);
					if(spell_flat_modifers!=0 || spell_pct_modifers!=0)
						printf("!!!!!spell duration mod flat %d , spell duration mod pct %d , spell duration %d, spell group %u\n",spell_flat_modifers,spell_pct_modifers,Dur,m_spellInfo->SpellGroupType);
#endif
                }
				// Limit duration in PvP but not applying diminishing returns
				if(unitTarget && unitTarget->IsPlayer() && this->Dur > 10000)
				{
					switch(m_spellInfo->NameHash)
					{
						case SPELL_HASH_CURSE_OF_TONGUES:
							this->Dur = 10000;
					}
				}
            }
            else
            {
                this->Dur = (uint32)-1;
            }
        }
        else
        {
             this->Dur = (uint32)-1;
        }

        return this->Dur;
    }

    ASCENT_INLINE float GetRadius(uint32 i)
    {
        if(bRadSet[i])return Rad[i];
        bRadSet[i]=true;
        Rad[i]=::GetRadius(dbcSpellRadius.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
        if(m_spellInfo->SpellGroupType && u_caster)
        {
            SM_FFValue(u_caster->SM_FRadius,&Rad[i],m_spellInfo->SpellGroupType);
            SM_PFValue(u_caster->SM_PRadius,&Rad[i],m_spellInfo->SpellGroupType);
#ifdef COLLECTION_OF_UNTESTED_STUFF_AND_TESTERS
			float spell_flat_modifers=0;
			float spell_pct_modifers=1;
			SM_FFValue(u_caster->SM_FRadius,&spell_flat_modifers,m_spellInfo->SpellGroupType);
			SM_PFValue(u_caster->SM_PRadius,&spell_pct_modifers,m_spellInfo->SpellGroupType);
			if(spell_flat_modifers!=0 || spell_pct_modifers!=1)
				printf("!!!!!spell radius mod flat %f , spell radius mod pct %f , spell radius %f, spell group %u\n",spell_flat_modifers,spell_pct_modifers,Rad[i],m_spellInfo->SpellGroupType);
#endif
        }

        return Rad[i];
    }

    ASCENT_INLINE static uint32 GetBaseThreat(uint32 dmg)
    {
        //there should be a formula to determine what spell cause threat and which don't
/*        switch(m_spellInfo->NameHash)
        {
            //hunter's mark
            case 4287212498:
                {
                    return 0;
                }break;
        }*/
        return dmg;
    }
    bool IsStealthSpell();
    bool IsInvisibilitySpell();
    
    int32 damage;
    Aura* m_triggeredByAura;
	signed int	forced_basepoints[3]; //some talent inherit base points from previous caster spells

    bool m_triggeredSpell;
    bool m_AreaAura;
    //uint32 TriggerSpellId;  // used to set next spell to use
    //uint64 TriggerSpellTarget; // used to set next spell target
    bool m_requiresCP;
    float m_castPositionX;
    float m_castPositionY;
    float m_castPositionZ;
   
    int32 damageToHit;
    uint32 castedItemId;
    bool judgement;
	uint8 extra_cast_number;

    void SendCastSuccess(Object * target);
    void SendCastSuccess(const uint64& guid);

    bool duelSpell;

	ASCENT_INLINE void safe_cancel()
	{
		m_cancelled = true;
	}

    /// Spell state's
    /// Spell failed
    ASCENT_INLINE bool GetSpellFailed(){return m_Spell_Failed;}
    ASCENT_INLINE void SetSpellFailed(bool failed = true){m_Spell_Failed = failed;}

    ASCENT_INLINE bool IsReflected() {return m_IsReflected;}
    ASCENT_INLINE void SetReflected(bool reflected = true) {m_IsReflected = reflected;}
    
    /// Spell possibility's
    ASCENT_INLINE bool GetCanReflect() {return m_CanRelect;}
    ASCENT_INLINE void SetCanReflect(bool reflect = true) {m_CanRelect = reflect;}


	Spell * m_reflectedParent;

protected:

    /// Spell state's
    bool    m_usesMana;
    bool    m_Spell_Failed;        //for 5sr
    bool    m_IsReflected;
    bool    m_Delayed;
    
    
    // Spell possibility's
    bool m_CanRelect;
    
    bool m_IsCastedOnSelf;

    bool hadEffect;

    uint32  m_spellState;
    int32   m_castTime;
    int32   m_timer;
    
    int64 m_magnetTarget;

    // Current Targets to be used in effect handler
    Unit*       unitTarget;
    Item*       itemTarget;
    GameObject* gameObjTarget;
    Player*     playerTarget;
    Corpse*     corpseTarget;
    uint32      add_damage;

    uint8       cancastresult;
    uint32      Dur;
    bool        bDurSet;
    float       Rad[3];
    bool        bRadSet[3];
	bool        m_cancelled;
	bool m_isCasting;
    //void _DamageRangeUpdate();

	ASCENT_INLINE bool HasTarget(const uint64& guid, TargetsList* tmpMap)
	{
		for(TargetsList::iterator itr = tmpMap->begin(); itr != tmpMap->end(); ++itr)
			if((*itr)==guid)
				return true;

		for(SpellTargetsList::iterator itr = ModeratedTargets.begin(); itr != ModeratedTargets.end(); ++itr)
			if((*itr).TargetGuid==guid)
				return true;

		return false;
	}

private:
    TargetsList m_targetUnits[3];
    void SafeAddTarget(TargetsList* tgt,uint64 guid);
    
    void SafeAddMissedTarget(uint64 guid);
    void SafeAddModeratedTarget(uint64 guid, uint16 type);

    friend class DynamicObject;
    void DetermineSkillUp(uint32 skillid,uint32 targetlevel);
    void DetermineSkillUp(uint32 skillid);
};

void ApplyDiminishingReturnTimer(uint32 * Duration, Unit * Target, SpellEntry * spell);
void UnapplyDiminishingReturnTimer(Unit * Target, SpellEntry * spell);
uint32 GetDiminishingGroup(uint32 NameHash);

#endif
